/**
 *******************************************************************************
 * @file    MDR12065_adcui.h
 * @author  Milandr Application Team
 * @version V0.2.0
 * @date    09/04/2026
 * @brief   This file contains all the functions prototypes for the ADCUI
 *          firmware library.
 *******************************************************************************
 * <br><br>
 *
 * THE PRESENT FIRMWARE IS FOR GUIDANCE ONLY. IT AIMS AT PROVIDING CUSTOMERS
 * WITH CODING INFORMATION REGARDING MILANDR'S PRODUCTS IN ORDER TO FACILITATE
 * THE USE AND SAVE TIME. MILANDR SHALL NOT BE HELD LIABLE FOR ANY
 * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES RESULTING
 * FROM THE CONTENT OF SUCH FIRMWARE AND/OR A USE MADE BY CUSTOMERS OF THE
 * CODING INFORMATION CONTAINED HEREIN IN THEIR PRODUCTS.
 *
 * <h2><center>&copy; COPYRIGHT 2026 Milandr</center></h2>
 *******************************************************************************
 */

/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef MDR12065_ADCUI_H
#define MDR12065_ADCUI_H

#ifdef __cplusplus
extern "C" {
#endif

/* Includes ------------------------------------------------------------------*/
#include "MDR12065_config.h"

/** @addtogroup MDR12065_StdPeriph_Driver MDR12065 Standard Peripheral Driver
 * @{
 */

/** @addtogroup ADCUI ADCUI
 * @{
 */

/** @defgroup ADCUI_Exported_Types ADCUI Exported Types
 * @{
 */

/**
 * @brief ADCUI channels definition.
 */
typedef enum {
    ADCUI_CH_F0_I0 = (((uint32_t)0x1) << ADCUI_CTRL1_I0EN_Pos),
    ADCUI_CH_F1_I1 = (((uint32_t)0x1) << ADCUI_CTRL1_I1EN_Pos),
    ADCUI_CH_F2_I2 = (((uint32_t)0x1) << ADCUI_CTRL1_I2EN_Pos),
    ADCUI_CH_F0_I3 = (((uint32_t)0X1) << ADCUI_CTRL1_I3EN_Pos)
} ADCUI_Channel_TypeDef;

#define IS_ADCUI_CHANNEL(CH)         (((CH) == ADCUI_CH_F0_I0) || \
                                      ((CH) == ADCUI_CH_F1_I1) || \
                                      ((CH) == ADCUI_CH_F2_I2) || \
                                      ((CH) == ADCUI_CH_F0_I3))

#define IS_ADCUI_CHANNEL_NO_I3(CH)   (((CH) == ADCUI_CH_F0_I0) || \
                                      ((CH) == ADCUI_CH_F1_I1) || \
                                      ((CH) == ADCUI_CH_F2_I2))

#define IS_ADCUI_CHANNELS(CHS)       (((CHS) & ~(uint32_t)(ADCUI_CH_F0_I0 | \
                                                           ADCUI_CH_F1_I1 | \
                                                           ADCUI_CH_F2_I2 | \
                                                           ADCUI_CH_F0_I3)) == 0)

#define IS_ADCUI_CHANNELS_NO_I3(CHS) (((CHS) & ~(ADCUI_CH_F0_I0 | \
                                                 ADCUI_CH_F1_I1 | \
                                                 ADCUI_CH_F2_I2)) == 0)

/**
 * @brief ADCUI status flags.
 */
typedef enum {
    ADCUI_Fx_IF_EMP   = ADCUI_FxSTAT_FxIF_EMP,
    ADCUI_Fx_IF_FLL   = ADCUI_FxSTAT_FxIF_FLL,
    ADCUI_Fx_IF_OVR   = ADCUI_FxSTAT_FxIF_OVR,
    ADCUI_Fx_C3IF_EMP = ADCUI_F0STAT_C3IF_EMP,
    ADCUI_Fx_C3IF_FLL = ADCUI_F0STAT_C3IF_FLL,
    ADCUI_Fx_C3IF_OVR = ADCUI_F0STAT_C3IF_OVR
} ADCUI_Flags_TypeDef;

#define ADCUI_FLAGS_MASK    (ADCUI_Fx_IF_EMP |   \
                             ADCUI_Fx_IF_FLL |   \
                             ADCUI_Fx_IF_OVR |   \
                             ADCUI_Fx_C3IF_EMP | \
                             ADCUI_Fx_C3IF_FLL | \
                             ADCUI_Fx_C3IF_OVR)

#define IS_ADCUI_FLAG(FLAG) (((FLAG) == ADCUI_Fx_IF_EMP) || ((FLAG) == ADCUI_Fx_IF_FLL) ||   \
                             ((FLAG) == ADCUI_Fx_IF_OVR) || ((FLAG) == ADCUI_Fx_C3IF_EMP) || \
                             ((FLAG) == ADCUI_Fx_C3IF_FLL) || ((FLAG) == ADCUI_Fx_C3IF_OVR))

/**
 * @brief ADCUI data output resolution (RESOL).
 */
typedef enum {
    ADCUI_DATA_RESOL_16BIT = (((uint32_t)0x0) << ADCUI_CTRL1_RESOL_Pos),
    ADCUI_DATA_RESOL_24BIT = (((uint32_t)0x1) << ADCUI_CTRL1_RESOL_Pos)
} ADCUI_DataResol_TypeDef;

#define IS_ADCUI_DATA_RESOL(RESOL) (((RESOL) == ADCUI_DATA_RESOL_16BIT) || \
                                    ((RESOL) == ADCUI_DATA_RESOL_24BIT))

/**
 * @brief ADCUI reference voltage configuration (VREF_SEL).
 */
typedef enum {
    ADCUI_REFERENCE_VOLTAGE_INTERNAL = (((uint32_t)0x1) << ADCUI_CTRL1_VREF_SEL_Pos),
    ADCUI_REFERENCE_VOLTAGE_EXTERNAL = (((uint32_t)0x0) << ADCUI_CTRL1_VREF_SEL_Pos)
} ADCUI_VRefConfig_TypeDef;

#define IS_ADCUI_REFERENCE_VOLTAGE(RV) (((RV) == ADCUI_REFERENCE_VOLTAGE_INTERNAL) || \
                                        ((RV) == ADCUI_REFERENCE_VOLTAGE_EXTERNAL))

/**
 * @brief ADCUI oversampling divider (OSR_CONF).
 */
typedef enum {
    ADCUI_OVERSAMPLING_DIV_1024 = ((uint32_t)(0x00) << ADCUI_CTRL1_OSR_CONF_Pos),     /*!< Frequency ADCUI divider (depends on the CLC_ADC_CFG setting). */
    ADCUI_OVERSAMPLING_DIV_512  = ((uint32_t)(0x01) << ADCUI_CTRL1_OSR_CONF_Pos),     /*!< Frequency ADCUI divider (depends on the CLC_ADC_CFG setting). */
    ADCUI_OVERSAMPLING_DIV_256  = (int)((uint32_t)(0x02) << ADCUI_CTRL1_OSR_CONF_Pos) /*!< Frequency ADCUI divider (depends on the CLC_ADC_CFG setting). */
} ADCUI_Divider_TypeDef;

#define IS_ADCUI_OSR_COF(COF) (((COF) == ADCUI_OVERSAMPLING_DIV_1024) || \
                               ((COF) == ADCUI_OVERSAMPLING_DIV_512) ||  \
                               ((COF) == ADCUI_OVERSAMPLING_DIV_256))

/**
 * @brief ADCUI clock frequency (CLC_ADC_CFG).
 */
typedef enum {
    ADCUI_CLK_FREQUENCY_4MHz = ((uint32_t)(0x00) << ADCUI_CLKPHASE1_CLC_ADC_CFG_Pos),
    ADCUI_CLK_FREQUENCY_2MHz = ((uint32_t)(0x01) << ADCUI_CLKPHASE1_CLC_ADC_CFG_Pos),
    ADCUI_CLK_FREQUENCY_1MHz = (int)((uint32_t)(0x02) << ADCUI_CLKPHASE1_CLC_ADC_CFG_Pos)
} ADCUI_ClockFrequency_TypeDef;

#define IS_ADCUI_CLK_FREQUENCY(FREQ)      (((FREQ) == ADCUI_CLK_FREQUENCY_4MHz) || \
                                           ((FREQ) == ADCUI_CLK_FREQUENCY_2MHz) || \
                                           ((FREQ) == ADCUI_CLK_FREQUENCY_1MHz))

#define IS_ADCUI_CLK_OSR_VALID(FREQ, COF) ((((FREQ) == ADCUI_CLK_FREQUENCY_1MHz) && ((COF) == ADCUI_OVERSAMPLING_DIV_256)) || \
                                           (((FREQ) == ADCUI_CLK_FREQUENCY_2MHz) && ((COF) == ADCUI_OVERSAMPLING_DIV_256)) || \
                                           (((FREQ) == ADCUI_CLK_FREQUENCY_2MHz) && ((COF) == ADCUI_OVERSAMPLING_DIV_512)) || \
                                           (((FREQ) == ADCUI_CLK_FREQUENCY_4MHz) && ((COF) == ADCUI_OVERSAMPLING_DIV_256)) || \
                                           (((FREQ) == ADCUI_CLK_FREQUENCY_4MHz) && ((COF) == ADCUI_OVERSAMPLING_DIV_512)) || \
                                           (((FREQ) == ADCUI_CLK_FREQUENCY_4MHz) && ((COF) == ADCUI_OVERSAMPLING_DIV_1024)))

/**
 * @brief ADCUI chopper period setting (CHP_ADC_CFG).
 */

typedef enum {
    ADCUI_CHOPPER_PERIOD_256  = ((uint32_t)(0x00) << ADCUI_FILTERCFG_CHP_ADC_CFG_Pos), /*!< The chopper period is 256 periods of the ADC clock signal (recommended for OSR_CONF = 256) */
    ADCUI_CHOPPER_PERIOD_512  = ((uint32_t)(0x01) << ADCUI_FILTERCFG_CHP_ADC_CFG_Pos), /*!< The chopper period is 512 periods of the ADC clock signal (recommended for OSR_CONF = 512) */
    ADCUI_CHOPPER_PERIOD_1024 = ((uint32_t)(0x02) << ADCUI_FILTERCFG_CHP_ADC_CFG_Pos)  /*!< The chopper period is 1024 periods of the ADC clock signal (recommended for OSR_CONF = 1024) */
} ADCUI_ChopperPeriod_TypeDef;

#define IS_ADCUI_CHOPPER_PERIOD(PERIOD) (((PERIOD) == ADCUI_CHOPPER_PERIOD_256) || \
                                         ((PERIOD) == ADCUI_CHOPPER_PERIOD_512) || \
                                         ((PERIOD) == ADCUI_CHOPPER_PERIOD_1024))

/**
 * @brief ADCUI Fx integrator state in the I channel (FxINTEN).
 */
typedef enum {
    ADCUI_INT_ENABLE  = (uint32_t)(0x00),
    ADCUI_INT_DISABLE = (uint32_t)(0x01)
} ADCUI_IntegratorState_TypeDef;

#define IS_ADCUI_INT_STATE(STATE) (((STATE) == ADCUI_INT_ENABLE) || \
                                   ((STATE) == ADCUI_INT_DISABLE))

/**
 * @brief ADCUI Fx gain in I channel (FxIGAIN).
 */
typedef enum {
    ADCUI_IGAIN_6dB  = (uint32_t)(0x00),
    ADCUI_IGAIN_12dB = (uint32_t)(0x01),
    ADCUI_IGAIN_18dB = (uint32_t)(0x02),
    ADCUI_IGAIN_24dB = (uint32_t)(0x03)
} ADCUI_IGain_TypeDef;

#define IS_ADCUI_IGAIN(IGAIN) (((IGAIN) == ADCUI_IGAIN_6dB) ||  \
                               ((IGAIN) == ADCUI_IGAIN_12dB) || \
                               ((IGAIN) == ADCUI_IGAIN_18dB) || \
                               ((IGAIN) == ADCUI_IGAIN_24dB))

/**
 * @brief ADCUI Fx unit number.
 */
typedef enum {
    ADCUI_F0_UNIT = (uint32_t)(0x00),
    ADCUI_F1_UNIT = (uint32_t)(0x01),
    ADCUI_F2_UNIT = (uint32_t)(0x02)
} ADCUI_Unit_TypeDef;

#define IS_ADCUI_UNIT(UNIT) (((UNIT) == ADCUI_F0_UNIT) || \
                             ((UNIT) == ADCUI_F1_UNIT) || \
                             ((UNIT) == ADCUI_F2_UNIT))

/**
 * @brief Specify the data (before or after the HPF filter) to be written into the ADCUI_F0I3DAT register in the F0I3SEL.
 */
typedef enum {
    ADCUI_F0I3SEL_AFTER_HPF  = (((uint32_t)0x0) << ADCUI_F0AC_F0I3SEL_Pos),
    ADCUI_F0I3SEL_BEFORE_HPF = (((uint32_t)0x1) << ADCUI_F0AC_F0I3SEL_Pos)
} ADCUI_F0_I3SelectDataFilter_TypeDef;

#define IS_ADCUI_F0I3SEL_SELECT(SELECT) (((SELECT) == ADCUI_F0I3SEL_AFTER_HPF) || \
                                         ((SELECT) == ADCUI_F0I3SEL_BEFORE_HPF))

/**
 * @brief Specify the data (before or after the HPF filter) to be written into the ADCUI_FxIDAT register.
 */
typedef enum {
    ADCUI_FxISEL_BEFORE_HPF = ((uint32_t)0x0),
    ADCUI_FxISEL_AFTER_HPF  = ((uint32_t)0x1)
} ADCUI_Fx_ISelectDataFilter_TypeDef;

#define IS_ADCUI_FxISEL_SELECT(SELECT) (((SELECT) == ADCUI_FxISEL_BEFORE_HPF) || \
                                        ((SELECT) == ADCUI_FxISEL_AFTER_HPF))

/**
 * @brief Selecting DMA operating mode (single or block transactions).
 */
typedef enum {
    ADCUI_DMA_TRANSACTIONS_SINGLE = ((uint32_t)0x0),
    ADCUI_DMA_TRANSACTIONS_BLOCK  = ((uint32_t)0x1)
} ADCUI_DmaTransMode_TypeDef;

#define IS_ADCUI_DMA_TRANSACTIONS_MODE(MODE) (((MODE) == ADCUI_DMA_TRANSACTIONS_SINGLE) || \
                                              ((MODE) == ADCUI_DMA_TRANSACTIONS_BLOCK))

/**
 * @brief ADCUI interrupt definition.
 */
typedef enum {
    ADCUI_Fx_IT_IF_EMP   = ADCUI_FxSTAT_FxIF_EMP,
    ADCUI_Fx_IT_IF_FLL   = ADCUI_FxSTAT_FxIF_FLL,
    ADCUI_Fx_IT_IF_OVR   = ADCUI_FxSTAT_FxIF_OVR,
    ADCUI_Fx_IT_C3IF_EMP = ADCUI_F0STAT_C3IF_EMP,
    ADCUI_Fx_IT_C3IF_FLL = ADCUI_F0STAT_C3IF_FLL,
    ADCUI_Fx_IT_C3IF_OVR = ADCUI_F0STAT_C3IF_OVR
} ADCUI_IT_TypeDef;

#define ADCUI_IT_MASK          (ADCUI_Fx_IT_IF_EMP |   \
                                ADCUI_Fx_IT_IF_FLL |   \
                                ADCUI_Fx_IT_IF_OVR |   \
                                ADCUI_Fx_IT_C3IF_EMP | \
                                ADCUI_Fx_IT_C3IF_FLL | \
                                ADCUI_Fx_IT_C3IF_OVR)

#define IS_ADCUI_ITS(IT)       (((IT) & (~(uint32_t)ADCUI_IT_MASK)) == 0)

#define IS_ADCUI_CONFIG_IT(IT) (((IT) == ADCUI_Fx_IT_IF_EMP) || ((IT) == ADCUI_Fx_IT_IF_FLL) ||   \
                                ((IT) == ADCUI_Fx_IT_IF_OVR) || ((IT) == ADCUI_Fx_IT_C3IF_EMP) || \
                                ((IT) == ADCUI_Fx_IT_C3IF_FLL) || ((IT) == ADCUI_Fx_IT_C3IF_OVR))

/**
 * @brief ADCUI init structure definition.
 */
typedef struct {
    ADCUI_DataResol_TypeDef ADCUI_DataResol;           /*!< Output data resolution.
                                                            This parameter can be a value of the @ref ADCUI_DataResol_TypeDef. */
    ADCUI_VRefConfig_TypeDef ADCUI_VRefConfig;         /*!< Selection of the reference voltage for the ADC and ADCUI.
                                                            This parameter can be a value of the @ref ADCUI_VRefConfig_TypeDef. */
    ADCUI_ClockFrequency_TypeDef ADCUI_ClockFrequency; /*!< Selecting the ADC clock frequency.
                                                            This parameter can be a value of the @ref ADCUI_ClockFrequency_TypeDef. */
    ADCUI_ChopperPeriod_TypeDef ADCUI_ChopperPeriod;   /*!< Setting the ADC chopper period of all channels.
                                                            This parameter can be a value of the @ref ADCUI_ChopperPeriod_TypeDef. */
    ADCUI_Divider_TypeDef ADCUI_Divider;               /*!< Selection of the oversampling factor.
                                                            This parameter can be a value of the @ref ADCUI_Divider_TypeDef. */
} ADCUI_InitTypeDef;

/**
 * @brief ADCUI Fx unit structure.
 */
typedef struct {
    ADCUI_IntegratorState_TypeDef ADCUI_Fx_IntegratorEnable;         /*!< The state of the integrator in the I channel.
                                                                          This parameter can be a value of the @ref ADCUI_IntegratorState_TypeDef */
    ADCUI_IntegratorState_TypeDef ADCUI_F0_I3IntegratorEnable;       /*!< The state of the integrator in the I3 channel in the F0 unit.
                                                                          This parameter can be a value of the @ref ADCUI_IntegratorState_TypeDef */
    ADCUI_IGain_TypeDef ADCUI_Fx_IGain;                              /*!< Specifies the level of the analog gain for I.
                                                                         This parameter can be a value of the @ref ADCUI_Gain_TypeDef */
    ADCUI_IGain_TypeDef ADCUI_F0_I3Gain;                             /*!< Specifies the level of the analog gain for I in the F0 unit.
                                                                         This parameter can be a value of the @ref ADCUI_Gain_TypeDef */
    ADCUI_F0_I3SelectDataFilter_TypeDef ADCUI_F0_I3SelectDataFilter; /*!< Selection of a signal source for the ADCUI_F0I3DAT register.
                                                                          This parameter can be a value of the @ref ADCUI_F0_I3SelectDataFilter_TypeDef */
    ADCUI_Fx_ISelectDataFilter_TypeDef ADCUI_Fx_ISelectDataFilter;   /*!< Selection of a signal source for the ADCUI_FxIDAT register.
                                                                          This parameter can be a value of the @ref ADCUI_Fx_ISelectDataFilter_TypeDef */
    uint16_t ADCUI_Fx_IGainCalibration;                              /*!< Current calibration value for the Fx unit.
                                                                          This parameter is a number from 0x0 to 0xFFFF. */
    uint16_t ADCUI_F0_I3GainCalibration;                             /*!< Current calibration value in the I3 channel, only for the F0.
                                                                          This parameter is a number from 0x0 to 0xFFFF. */
} ADCUI_FxUnit_InitTypeDef;

/** @} */ /* End of the group ADCUI_Exported_Types */

/** @defgroup ADCUI_Exported_Functions ADCUI Exported Functions
 * @{
 */

void ADCUI_DeInit(void);
void ADCUI_Init(const ADCUI_InitTypeDef* ADCUI_InitStruct);
void ADCUI_StructInit(ADCUI_InitTypeDef* ADCUI_InitStruct);
void ADCUI_ResetDigital(FunctionalState NewState);

void ADCUI_Fx_Init(ADCUI_Unit_TypeDef UnitNumber, const ADCUI_FxUnit_InitTypeDef* ADCUI_FxUnitInitStruct);
void ADCUI_Fx_StructInit(ADCUI_FxUnit_InitTypeDef* ADCUI_FxUnitInitStruct);
void ADCUI_ChannelConfig(uint32_t Channels, FunctionalState NewState);

uint32_t ADCUI_GetResult(ADCUI_Channel_TypeDef ChannelNumber);

void ADCUI_DMAConfig(uint32_t Channels, ADCUI_DmaTransMode_TypeDef Mode, FunctionalState NewState);
void ADCUI_ChopperConfig(ADCUI_Channel_TypeDef ChannelNumber, FunctionalState NewState);

void       ADCUI_ClearFlags(ADCUI_Unit_TypeDef UnitNumber, uint32_t Flags);
FlagStatus ADCUI_GetFlagStatus(ADCUI_Unit_TypeDef UnitNumber, ADCUI_Flags_TypeDef ADCUI_Flag);
uint32_t   ADCUI_GetStatus(ADCUI_Unit_TypeDef UnitNumber);

void ADCUI_ITConfig(ADCUI_Unit_TypeDef UnitNumber, uint32_t ADCUI_IT, FunctionalState NewState);

/** @} */ /* End of the group ADCUI_Exported_Functions */

/** @} */ /* End of the group ADCUI */

/** @} */ /* End of the group MDR12065_StdPeriph_Driver */

#ifdef __cplusplus
} // extern "C" block end
#endif

#endif /* MDR12065_ADCUI_H */

/*********************** (C) COPYRIGHT 2026 Milandr ****************************
 *
 * END OF FILE MDR12065_adcui.h */

